// 信息汇总

package student

import (
	"api/common"
	"api/common/logger"
	"api/common/orm"
	"api/common/web"
	"api/models"
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

// @TagName 信息汇总
// @Controller GatherController
type GatherController struct{}

// @Title 信息汇总列表数据
// @Route /gather/list --> List
// @Method post
func (this *GatherController) List(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	wheres, limit := web.SerachJsonToSql(inputJson)
	where := " where `status` = 5" // 5: 交费成功
	if len(wheres) > 0 {
		where += " and "

		whereData := []string{}
		for _, item := range wheres {
			// 查询外地学生稍微麻烦一些
			if item == "resid_type = '0'" {
				// 长治市以外的地区
				item = "(resid_type < 140400 or resid_type > 140431)"
			}
			whereData = append(whereData, item)
		}

		where += strings.Join(whereData, " and ")
	}

	sql := ""
	var err error
	conn := orm.NewOrm()
	ids := inputJson["specialIds"]
	if ids != nil {
		where += " and special_id in (" + common.ToStr(ids) + ")"
	} else {
		// specialIds未指定，获取当前用户的可见系部
		userId := inputJson["userId"]
		depts := ""
		sql = "select depts from basic_user where id = ?"
		err = conn.Raw(sql, userId).QueryRow(&depts)
		if err != nil {
			logger.Error("查询用户可见系部发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询用户可见系部发生错误" + err.Error(), 1})
			return
		}

		if depts != "" {
			// 用户的可见系部
			idData := []uint32{}
			sql = "select id from basic_special where pid in (%s)"
			sql = fmt.Sprintf(sql, depts)
			_, err = conn.Raw(sql).QueryRows(&idData)
			if err != nil {
				logger.Error("查询用户可见系部发生错误", err)
				web.ServeJSON(w, web.JsonMsg{false, "查询用户可见系部发生错误" + err.Error(), 1})
				return
			}

			idText := "" // 专业的id集合
			for i := 0; i < len(idData); i += 1 {
				id := idData[i]
				idText += orm.ToStr(id)
				if i < len(idData)-1 {
					idText += ","
				}
			}
			where += " and special_id in (" + idText + ")"
		}
	}

	type Counts struct {
		Total        uint32 `json:"total"`
		Lodging1sex1 uint32 `json:"lodging1sex1"`
		Lodging1sex0 uint32 `json:"lodging1sex0"`
		Lodging0sex1 uint32 `json:"lodging0sex1"`
		Lodging0sex0 uint32 `json:"lodging0sex0"`
		Exitsex1     uint32 `json:"exitsex1"`
		Exitsex0     uint32 `json:"exitsex0"`
	}
	counts := &Counts{}
	sql = "select" +
		" (select count(1) from student_info" + where + ") total," +
		" (select count(1) from student_info" + where + " and lodging=true  and sex=true)  lodging1sex1," +
		" (select count(1) from student_info" + where + " and lodging=true  and sex=false) lodging1sex0," +
		" (select count(1) from student_info" + where + " and lodging=false and sex=true)  lodging0sex1," +
		" (select count(1) from student_info" + where + " and lodging=false and sex=false) lodging0sex0," +
		" (select count(1) from student_info" + where + " and `exit`=true  and sex=true)  exitsex1," +
		" (select count(1) from student_info" + where + " and `exit`=true  and sex=false) exitsex0"
	err = conn.Raw(sql).QueryRow(counts)
	if err != nil {
		logger.Error("查询记录数量发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "查询记录数量发生错误" + err.Error(), 1})
		return
	}

	data := []map[string]interface{}{}
	if counts.Total > 0 {
		fields := "id, `name`, sex, address, phone, id_card_num, exam_card_num," +
			" signup, sum, special_id, type, lodging, school, fee, fee_time, `exit`, resid_type"
		sql = "select " + fields + " from student_info" + where +
			" order by special_id, lodging desc, sex desc, add_time" + limit
		data, err = conn.Raw(sql).QueryMaps()
		if err != nil {
			logger.Error("查询记录发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询记录发生错误" + err.Error(), 1})
			return
		}
	}

	result := map[string]interface{}{}
	result["status"] = 0
	result["success"] = true
	result["msg"] = "查询成功"
	result["data"] = data
	result["counts"] = counts
	web.ServeJSON(w, result)
}

// @Title 信息汇总列表数据(返回所有字段)
// @Route /gather/listAll --> ListAll
// @Method post
func (this *GatherController) ListAll(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	ids := inputJson["ids"]
	model := &models.Info{}
	where := "`status`=5" // 5: 交费成功
	if ids != nil && ids != "" {
		where += " and id in (" + common.ToStr(ids) + ")"
	}
	order := "`status`, add_time"
	page, msg := web.JsonRootWithInputFilter(inputJson, model, "", where, order)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	// 对审核通过的学生记录，附加审核员姓名
	sql := "select id, `name` from basic_user"
	arr := []models.User{}
	conn := orm.NewOrm()
	_, err := conn.Raw(sql).QueryRows(&arr)
	if err != nil {
		logger.Error("查询id与name的映射关系发生错误：", err.Error())
		web.ServeJSON(w, web.JsonMsg{false, err.Error(), 1})
		return
	}

	obj := map[uint32]string{}
	for _, item := range arr {
		obj[item.Id] = item.Name
	}

	for i := 0; i < len(page.Root); i += 1 {
		item := page.Root[i]
		id, _ := strconv.Atoi(item["auditAdmin"].(string))
		page.Root[i]["auditAdminName"] = obj[uint32(id)]
	}

	web.ServeJSON(w, page)
}

// @Title 带统计人数的专业列表数据
// @Route /gather/listSpecial --> ListSpecial
// @Method post
func (this *GatherController) ListSpecial(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	userId := inputJson["userId"]
	depts := ""
	sql := "select depts from basic_user where id = ?"
	conn := orm.NewOrm()
	err := conn.Raw(sql, userId).QueryRow(&depts)
	if err != nil {
		logger.Error("查询用户可见系部发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "查询用户可见系部发生错误" + err.Error(), 1})
		return
	}

	where := ""
	sql = "select s.id, s.pid, s.`name`, s.types," +
		" (select count(1) from student_info i where i.`status`=5 and i.special_id=s.id) count" +
		" from basic_special s %s order by count desc, s.sequ desc"
	if depts != "" {
		// 用户的可见系部
		where = "where s.id in (%s) or s.pid in (%s)"
		where = fmt.Sprintf(where, depts, depts)
	}
	sql = fmt.Sprintf(sql, where)
	data := []map[string]interface{}{}
	data, err = conn.Raw(sql).QueryMaps()
	if err != nil {
		logger.Error("查询记录发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "查询记录发生错误" + err.Error(), 1})
		return
	}

	result := map[string]interface{}{}
	result["status"] = 0
	result["success"] = true
	result["msg"] = "查询成功"
	result["data"] = data
	web.ServeJSON(w, result)
}

// @Title 调整学生报名信息
// @Route /gather/edit --> Edit
// @Param {"userId":0,"token":"","data":{}}
// @Method post
func (this *GatherController) Edit(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	data := inputJson["data"]
	if data == nil {
		web.ServeJSON(w, web.JsonMsg{false, "报名信息不能为空", 1})
		return
	}

	modelMap := data.(map[string]interface{})
	user := &models.Info{}
	web.JsonToStruct(modelMap, user)

	sql := "select * from student_info where id=? and (`status`=2 or `status`=5)"
	conn := orm.NewOrm()
	err := conn.Raw(sql, user.Id).QueryRow(user)
	if err != nil {
		if strings.Index(err.Error(), "no row found") == -1 {
			logger.Info("验证用户信息发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "验证用户信息发生错误" + err.Error(), 1})
			return
		}

		web.ServeJSON(w, web.JsonMsg{false, "学生记录不存在", 1})
		return
	}

	web.JsonToStruct(modelMap, user)

	if user.WeixinId != "" {
		// 检查"操作记录"里是否有依据(是否有前一状态的记录)
		count := 0
		sql = "select count(1) from student_operate_record where" +
			" student_id=? and add_time<now() and" +
			" `status`=2 and admin_id>0 and remark=''" +
			" order by add_time desc"
		err = conn.Raw(sql, user.Id).QueryRow(&count)
		if err != nil {
			logger.Error("查询操作记录数量发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询操作记录数量发生错误" + err.Error(), 1})
			return
		}
		if count == 0 {
			web.ServeJSON(w, web.JsonMsg{false, "“操作记录”表里没有前一状态的记录", 1})
			return
		}
	}

	_, err = conn.Update(user)
	if err != nil {
		logger.Error("更新记录发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "更新记录发生错误" + err.Error(), 1})
		return
	}

	web.ServeJSON(w, web.JsonMsg{true, "调整学生信息操作成功", 0})
}

// @Title 删除学生报名信息
// @Route /gather/delete --> Delete
// @Method post
func (this *GatherController) Delete(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	web.DeleteCallBak(w, r, &models.Info{})
}

// @Title 学生退学
// @Route /gather/exit --> Exit
// @Param {"userId":0,"token":"","ids":""}
// @Method post
func (this *GatherController) Exit(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.DeleteCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	ids := inputJson["ids"].(string)

	// 只更新交费成功的学生状态
	sql := "update student_info set `exit` = true" +
		" where id in (" + ids + ") and `status` = 5"
	conn := orm.NewOrm()
	result, err := conn.Raw(sql).Exec()
	if err != nil {
		logger.Error("更新记录发生错误：", err)
		web.ServeJSON(w, web.JsonMsg{false, "更新记录发生错误：" + err.Error(), 1})
		return
	}

	count, err := result.RowsAffected()
	if err != nil {
		logger.Error(err)
		web.ServeJSON(w, web.JsonMsg{false, err.Error(), 1})
		return
	}

	if count == 0 {
		web.ServeJSON(w, web.JsonMsg{true, "没有学生退学。", 0})
		return
	}

	web.ServeJSON(w, web.JsonMsg{true, common.ToStr(count) + "个学生退学成功。", 0})
}

// @Title 撤销退学
// @Route /gather/exitUndo --> ExitUndo
// @Param {"userId":0,"token":"","studentId":0}
// @Method post
func (this *GatherController) ExitUndo(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	id := inputJson["studentId"]
	if id == nil {
		web.ServeJSON(w, web.JsonMsg{false, "学生id不能为空", 1})
		return
	}

	sql := "update student_info set `exit` = false" +
		" where id = " + common.ToStr(id)
	conn := orm.NewOrm()
	_, err := conn.Raw(sql).Exec()
	if err != nil {
		logger.Error("更新记录发生错误：", err)
		web.ServeJSON(w, web.JsonMsg{false, "更新记录发生错误：" + err.Error(), 1})
		return
	}

	web.ServeJSON(w, web.JsonMsg{true, "撤销退学成功", 0})
}
